package com.alibaba.citrus.ots.sales.plan.facade.service.salesplan;

import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.model.ApiContext;
import com.alibaba.citrus.ots.sales.plan.api.salesplan.SalesPlanLineQueryService;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.DimensionDTO;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.PageQueryPlanLineRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.request.SalesPlanSubTotalRequest;
import com.alibaba.citrus.ots.sales.plan.dto.api.response.SalesPlanSubTotalResponse;
import com.alibaba.citrus.ots.sales.plan.facade.service.SalesPlanCommonService;
import com.alibaba.citrus.ots.sales.plan.facade.service.SalesPlanOutCommonService;
import com.alibaba.citrus.ots.sales.plan.model.enums.SalesStatBizTypeEnum;
import com.alibaba.citrus.ots.sales.plan.repository.SalesPlanLineRepository;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanLineSDO;
import com.alibaba.citrus.ots.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.model.dto.ScItemSDO;
import com.epoch.app.bcots.sales_plan.bosalesplandetailindex.dto.PageQueryPlanDetailRequest;
import com.epoch.app.bcots.sales_plan.bosalesplandetailindex.dto.PageQueryPlanDetailResponse;
import com.epoch.app.bcots.sales_plan.bosalesplandetailindex.service.BoSalesPlanDetailIndexService;
import com.epoch.app.otsplatformenhance.enums.OrganizationTypeEnum;
import com.epoch.app.otsplatformenhance.model.dto.CustomerAddressIndex;
import com.epoch.app.otsunifiedinventory.model.dto.GetStoreInventoryAggreRequest;
import com.epoch.app.otsunifiedinventory.model.dto.WarehouseInventory;
import com.epoch.app.otsunifiedinventory.service.OtsUnifiedInventoryService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author wangyibing
 */
@Service
public class SalesPlanLineQueryServiceImpl implements SalesPlanLineQueryService {

    private static final Log log = Log.getLogger(SalesPlanLineQueryServiceImpl.class);

    @Resource
    private SalesPlanLineRepository salesPlanLineRepository;

    @Resource
    private SalesPlanCommonService salesPlanCommonService;

    @Autowired(required = false)
    private OtsUnifiedInventoryService otsUnifiedInventoryService;

    @Autowired
    private BoSalesPlanDetailIndexService boSalesPlanDetailIndexService;

    @Resource
    private SalesPlanOutCommonService salesPlanOutCommonService;

    @Override
    @FacadeInvoker
    public Result<PageResult<List<SalesPlanLineSDO>>> pageQuerySalesPlanLineList(PageQueryPlanLineRequest queryPlanLineRequest) {
        PageQueryPlanDetailRequest detailRequest = getPageQueryPlanDetailRequest(queryPlanLineRequest);
        PageQueryPlanDetailResponse planDetailResponse = boSalesPlanDetailIndexService.pageQueryPlanDetail(detailRequest);
        if (planDetailResponse == null || CollectionUtils.isEmpty(planDetailResponse.getResult())) {
            return Result.success(new PageResult<>(Lists.newArrayList(), 0));
        }
        List<SalesPlanLineSDO> collect = planDetailResponse.getResult().stream().map(detail -> {
            SalesPlanLineSDO sdo = SalesPlanLineSDO.builder().build();
            BeanUtils.copyProperties(detail, sdo);
            sdo.setCustomerName(detail.getSubCustomerName());
            sdo.setCustomerAddressName(detail.getSubCustomerAddressName());
            sdo.setScItemName(detail.getSubScItemName());
            sdo.setMonthReturnCount(sdo.getMonthFirstReturnCount() + sdo.getMonthMiddleReturnCount() + sdo.getMonthLastReturnCount());
            sdo.setMonthAdjustReturnCount(sdo.getMonthFirstAdjustReturnCount() + sdo.getMonthMiddleAdjustReturnCount() + sdo.getMonthLastAdjustReturnCount());
            if (detail.getAppletSubmission() == null) {
                sdo.setAppletSubmission(false);
            } else {
                sdo.setAppletSubmission(detail.getAppletSubmission());
            }
            return sdo;
        }).collect(Collectors.toList());
        PageResult<List<SalesPlanLineSDO>> pageResult = new PageResult<>(collect, planDetailResponse.getTotal());
        if (collect.size() > 0) {
            pageResultConverter(pageResult);
        }
        return Result.success(pageResult);
    }

    private PageQueryPlanDetailRequest getPageQueryPlanDetailRequest(PageQueryPlanLineRequest queryPlanLineRequest) {
        PageQueryPlanDetailRequest detailRequest = new PageQueryPlanDetailRequest();
        SalesPlanSDO salesPlan = salesPlanCommonService.checkSalesPlan(queryPlanLineRequest.getPlanId());
        DimensionDTO dimension = salesPlanCommonService.checkBizType(salesPlan, queryPlanLineRequest);
        SalesStatBizTypeEnum byOrganizationType = SalesStatBizTypeEnum.match(dimension.getBizType());
        switch (byOrganizationType) {
            case SALESMAN:
                detailRequest.setManageEmployeeIdList(Lists.newArrayList(dimension.getBizId()));
                break;
            case SALES_DEPARTMENT:
                detailRequest.setOrgSalesDepartmentCode(dimension.getBizId());
                break;
            case SALES_CHANNEL:
                detailRequest.setOrgSalesChannelCode(dimension.getBizId());
                break;
            case SALES_ORGANIZATION:
                detailRequest.setOrgSalesOrganizationCode(dimension.getBizId());
                break;
            case BUSINESS_UNIT:
                detailRequest.setOrgBusinessUnitCode(dimension.getBizId());
                break;
            default:
        }
        detailRequest.setAsc(queryPlanLineRequest.getAsc() == null || queryPlanLineRequest.getAsc());
        detailRequest.setField(queryPlanLineRequest.getDir());
        detailRequest.setPlanId(queryPlanLineRequest.getPlanId());
        detailRequest.setChannelCode(queryPlanLineRequest.getChannelCode());

        if (StringUtils.isNotBlank(queryPlanLineRequest.getCustomerCode())) {
            detailRequest.setCustomerCodeList(Lists.newArrayList(queryPlanLineRequest.getCustomerCode()));
        }
        if (StringUtils.isNotBlank(queryPlanLineRequest.getCustomerAddress())) {
            detailRequest.setCustomerAddressList(Lists.newArrayList(queryPlanLineRequest.getCustomerAddress()));
        }
        if (StringUtils.isNotBlank(queryPlanLineRequest.getManageEmployeeId())) {
            detailRequest.setManageEmployeeIdList(Lists.newArrayList(queryPlanLineRequest.getManageEmployeeId()));
        }
        if (StringUtils.isNotBlank(queryPlanLineRequest.getScItemId())) {
            detailRequest.setScItemIdList(Lists.newArrayList(queryPlanLineRequest.getScItemId()));
        }
        if (StringUtils.isNotBlank(queryPlanLineRequest.getScItemGroup())) {
            detailRequest.setScItemGroupList(Lists.newArrayList(queryPlanLineRequest.getScItemGroup()));
        }
        if (StringUtils.isNotBlank(queryPlanLineRequest.getScItemLeafCategoryId())) {
            detailRequest.setScItemLeafCategoryIdList(Lists.newArrayList(queryPlanLineRequest.getScItemLeafCategoryId()));
        }
        if (StringUtils.isNotBlank(queryPlanLineRequest.getCustomerAddressId())) {
            detailRequest.setCustomerAddressId(queryPlanLineRequest.getCustomerAddressId());
        }

        detailRequest.setAppletSubmission(queryPlanLineRequest.getAppletSubmission());
        detailRequest.setStatus(queryPlanLineRequest.getStatus());
        detailRequest.setContractDifferenceMoneyStamp(queryPlanLineRequest.getContractDifferenceMoneyStamp());
        detailRequest.setCustomerName(queryPlanLineRequest.getCustomerName());
        detailRequest.setCustomerAddressName(queryPlanLineRequest.getCustomerAddressName());
        detailRequest.setScItemName(queryPlanLineRequest.getScItemName());
        detailRequest.setStart(queryPlanLineRequest.getStart());
        detailRequest.setLimit(queryPlanLineRequest.getLimit());
        return detailRequest;
    }

    private void pageResultConverter(PageResult<List<SalesPlanLineSDO>> pageResult) {
        Set<String> scItemSet = Sets.newHashSet();
        Set<String> customerAddressSet = Sets.newHashSet();
        Set<String> customerSet = Sets.newHashSet();
        Set<String> orgSalesOrganizationCodeSet = Sets.newHashSet();
        Set<String> channelCodeSet = Sets.newHashSet();
        pageResult.getContent().forEach(salesPlanLineSDO -> {
            scItemSet.add(salesPlanLineSDO.getScItemId());
            customerAddressSet.add(salesPlanLineSDO.getCustomerAddress());
            customerSet.add(salesPlanLineSDO.getCustomerCode());
            orgSalesOrganizationCodeSet.add(salesPlanLineSDO.getOrgSalesOrganizationCode());
            channelCodeSet.add(salesPlanLineSDO.getChannelCode());
        });
        //获取货品外部编码
        Map<String, ScItemSDO> scItemMapByOutMap = salesPlanOutCommonService.getScItemMapByIds(scItemSet, false);
        if (scItemMapByOutMap == null){
            log.error("SalesPlanLineQueryServiceImpl.pageResultConverter scItemMapByOutMap is null");
            return;
        }
        //取门店库存
        Map<String, CustomerAddressIndex> customerAddressByFive = salesPlanOutCommonService.getCustomerAddressByFive(customerAddressSet, customerSet, orgSalesOrganizationCodeSet, channelCodeSet, null);
        if(null == customerAddressByFive){
            log.error("SalesPlanLineQueryServiceImpl.pageResultConverter customerAddressByFive is null");
            return;
        }
        List<String> addressIdCollect = customerAddressByFive.values().stream().map(index -> {
            return Objects.toString(index.getId());
        }).collect(Collectors.toList());
        GetStoreInventoryAggreRequest getStoreInventoryAggreRequest = new GetStoreInventoryAggreRequest();
        getStoreInventoryAggreRequest.setAddressCodeList(addressIdCollect);
        getStoreInventoryAggreRequest.setGoodsIds(Lists.newArrayList(scItemSet));
        Map<String, WarehouseInventory> businessInventoryMap = Maps.newHashMap();
        try {
            Result<List<WarehouseInventory>> listResult = otsUnifiedInventoryService.getStoreInventoryAggre(getStoreInventoryAggreRequest);
            if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
                businessInventoryMap = listResult.getResult()
                        .stream().collect(Collectors.toMap(x -> x.getGoodsId() + x.getAddressCode(), a -> a, (a, b) -> a));
            }
        }catch (Exception e){
            log.error("SalesPlanLineQueryServiceImpl.searchBusinessInventoryByPage.exception:{}",e);
        }
        Map<String, WarehouseInventory> finalBusinessInventoryMap = businessInventoryMap;
        for (SalesPlanLineSDO salesPlanLineSDO : pageResult.getContent()) {
            salesPlanLineSDO.setInventory(0);
            if (!Objects.isNull(scItemMapByOutMap) && !scItemMapByOutMap.isEmpty()) {
                ScItemSDO scItemSDO = scItemMapByOutMap.get(salesPlanLineSDO.getScItemId());
                if (Objects.nonNull(scItemSDO)) {
                    //外部编码
                    salesPlanLineSDO.setOuterId(scItemSDO.getOuterId());
                }
            }
            CustomerAddressIndex customerAddressIndex = customerAddressByFive.get(salesPlanLineSDO.getCustomerCode() + salesPlanLineSDO.getCustomerAddress() + salesPlanLineSDO.getOrgSalesOrganizationCode() + salesPlanLineSDO.getChannelCode());
            if (customerAddressIndex == null) {
                salesPlanLineSDO.setInventoryStr("0");
                continue;
            }
            WarehouseInventory warehouseInventory = finalBusinessInventoryMap.get(salesPlanLineSDO.getScItemId() + customerAddressIndex.getId());
            if (Objects.nonNull(warehouseInventory)) {
                salesPlanLineSDO.setInventoryStr(warehouseInventory.getAvailableQuantityFormat());
            } else {
                salesPlanLineSDO.setInventoryStr("0");
            }
        }
    }

    @Override
    @FacadeInvoker
    public Result<SalesPlanSubTotalResponse> subTotalSalesPlanLine(SalesPlanSubTotalRequest salesPlanSubTotalRequest) {
        SalesPlanSDO salesPlan = salesPlanCommonService.checkSalesPlan(salesPlanSubTotalRequest.getPlanId());
        DimensionDTO dimension = salesPlanCommonService.checkBizType(salesPlan, salesPlanSubTotalRequest);
        SalesStatBizTypeEnum byOrganizationType = SalesStatBizTypeEnum.match(dimension.getBizType());
        switch (byOrganizationType) {
            case SALESMAN:
                salesPlanSubTotalRequest.setManageEmployeeId(dimension.getBizId());
                break;
            case SALES_DEPARTMENT:
                salesPlanSubTotalRequest.setOrgSalesDepartmentCode(dimension.getBizId());
                break;
            case SALES_CHANNEL:
                salesPlanSubTotalRequest.setOrgSalesChannelCode(dimension.getBizId());
                break;
            case SALES_ORGANIZATION:
                salesPlanSubTotalRequest.setOrgSalesOrganizationCode(dimension.getBizId());
                break;
            case BUSINESS_UNIT:
                salesPlanSubTotalRequest.setOrgBusinessUnitCode(dimension.getBizId());
                break;
            default:
        }
        SalesPlanSubTotalResponse salesPlanSubTotalResponse = salesPlanLineRepository.subTotalSalesPlanLine(salesPlanSubTotalRequest);
        return Result.success(salesPlanSubTotalResponse);
    }

    @Override
    @FacadeInvoker
    public Result<BigDecimal> queryCompletePercent(SalesPlanSubTotalRequest salesPlanSubTotalRequest) {
        SalesPlanSDO salesPlan = salesPlanCommonService.checkSalesPlan(salesPlanSubTotalRequest.getPlanId());
        DimensionDTO dimension = salesPlanCommonService.checkBizType(salesPlan, salesPlanSubTotalRequest);
        SalesStatBizTypeEnum byOrganizationType = SalesStatBizTypeEnum.match(dimension.getBizType());
        switch (byOrganizationType) {
            case SALESMAN:
                salesPlanSubTotalRequest.setManageEmployeeId(dimension.getBizId());
                break;
            case SALES_DEPARTMENT:
                salesPlanSubTotalRequest.setOrgSalesDepartmentCode(dimension.getBizId());
                break;
            case SALES_CHANNEL:
                salesPlanSubTotalRequest.setOrgSalesChannelCode(dimension.getBizId());
                break;
            case SALES_ORGANIZATION:
                salesPlanSubTotalRequest.setOrgSalesOrganizationCode(dimension.getBizId());
                break;
            case BUSINESS_UNIT:
                salesPlanSubTotalRequest.setOrgBusinessUnitCode(dimension.getBizId());
                break;
            default:
        }
        return Result.success(salesPlanLineRepository.queryCompletePercent(salesPlanSubTotalRequest));
    }

    @Override
    @FacadeInvoker
    public Result<List<String>> querySalesPlanLineByCustomerAddress(SalesPlanSubTotalRequest salesPlanSubTotalRequest) {
        return Result.success(salesPlanLineRepository.querySalesPlanLineByCustomerAddress(salesPlanSubTotalRequest));
    }

    @Override
    @FacadeInvoker
    public Result<List<String>> querySalesPlanLineByScItem(SalesPlanSubTotalRequest salesPlanSubTotalRequest) {
        return Result.success(salesPlanLineRepository.querySalesPlanLineByScItem(salesPlanSubTotalRequest));
    }

    private Result<Boolean> salesPlanData(ApiContext apiContext, PageQueryPlanLineRequest pageQueryPlanLineRequest) {
        if (apiContext.getIsSales() != null && apiContext.getIsSales()) {
            if (StringUtils.isNotEmpty(pageQueryPlanLineRequest.getManageEmployeeId())) {
                if (!apiContext.getEmployeeId().equals(pageQueryPlanLineRequest.getManageEmployeeId())) {
                    throw new FacadeException("OTS-01-003-01-16-002");
                }
            }
            return Result.success(true);
        }
        OrganizationTypeEnum typeEnum = Arrays.stream(OrganizationTypeEnum.values()).filter(
                        s -> s.getCode().equals(pageQueryPlanLineRequest.getBizType()))
                .findFirst().orElse(null);
        if (Objects.isNull(typeEnum)) {
            throw new FacadeException("OTS-01-003-01-16-001");
        }
        if (apiContext.getRelatedOrganizationType() > pageQueryPlanLineRequest.getBizType()) {
            throw new FacadeException("OTS-01-003-01-16-002");
        }
        if (apiContext.getRelatedOrganizationType().equals(pageQueryPlanLineRequest.getBizType())) {
            if (!apiContext.getBelongOrganizationId().equals(pageQueryPlanLineRequest.getBizId())) {
                throw new FacadeException("OTS-01-003-01-16-002");
            }
        }
        return Result.success(true);
    }

}
